package org.moonlight.jvm.instructions.references;

import org.moonlight.jvm.instructions.base.Index16Instruction;
import org.moonlight.jvm.rtda.exclusive.Frame;
import org.moonlight.jvm.rtda.exclusive.OperandStack;
import org.moonlight.jvm.rtda.share.Object;
import org.moonlight.jvm.rtda.share.heap.Class;
import org.moonlight.jvm.rtda.share.heap.symref.ClassRef;
import org.moonlight.jvm.rtda.share.methodarea.RtConstantPool;

/**
 * checkcast: checkcast指令和instanceof指令很像，区别在于：
 *            instanceof指令会改变操作数栈（弹出对象引用，推入判断结果）;
 *            checkcast则不改变操作数栈（如果判断失败，直接抛出ClassCastException异常）
 *
 * @author Moonlight
 * @createTime 2023/8/30 15:52
 **/
public class CheckCast extends Index16Instruction {

    @Override
    public void execute(Frame frame) {
        OperandStack operandStack = frame.getOperandStack();
        Object ref = operandStack.popRef();
        operandStack.pushRef(ref);
        // null引用可以转换成任何类型
        if (ref == null) {
            return;
        }

        RtConstantPool rtCp = frame.getMethod().getClazz().getRtCp();
        ClassRef classRef = (ClassRef) rtCp.getConstant(this.idx);
        Class clazz = classRef.resolvedClass();
        if (!ref.isInstanceOf(clazz)) {
            throw new ClassCastException();
        }
    }

}